package com.aos.erp.gov.ex.task.cq;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.aos.erp.common.constant.GlobalConstant;
import com.aos.erp.common.exception.BizException;
import com.aos.erp.common.redis.RedisService;
import com.aos.erp.common.utils.DateUtils;
import com.aos.erp.common.utils.JsonUtils;
import com.aos.erp.common.utils.NumUtil;
import com.aos.erp.gov.ex.enums.RegisterTaskType;
import com.aos.erp.gov.ex.model.GovExSyncTask;
import com.aos.erp.gov.ex.model.GovSchoolTicket;
import com.aos.erp.gov.ex.model.dto.CheckResultFailDTO;
import com.aos.erp.gov.ex.model.ro.AddStudentExamRo;
import com.aos.erp.gov.ex.model.ro.AddStudentFieldRo;
import com.aos.erp.gov.ex.model.ro.FieldStatus;
import com.aos.erp.gov.ex.model.to.GovKSCX;
import com.aos.erp.gov.ex.model.to.GovKSDD;
import com.aos.erp.gov.ex.model.to.GovKSKM;
import com.aos.erp.gov.ex.service.GovExRegisterTaskService;
import com.aos.erp.gov.ex.service.remote.StudentExamService;
import com.aos.erp.gov.ex.task.SyncExecuteCenter;
import com.aos.erp.gov.ex.utils.HttpClientUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.*;

@Slf4j
@Component
public class CQSyncExecuteCenter implements SyncExecuteCenter {

    private String jsonSuccessCode = "200";
    @Resource
    private RedisService redisService;
    @Resource
    private StudentExamService examService;
    @Resource
    private GovExRegisterTaskService exRegisterTaskService;

    public Map<String, String> getHeaderMap(GovSchoolTicket ticket) {
        Map<String, String> header = new HashMap<String, String>();
        header.put("Host", ticket.getWebCode());
        header.put("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36");
        header.put("Cookie", ticket.getCookies());
        return header;
    }

    @Override
    public boolean isWebOwner(GovSchoolTicket ticket) {
        return true;
    }

    @Override
    public void keepLive(GovSchoolTicket ticket) throws BizException {
        HttpClientUtil.post("http://" + ticket.getWebCode() + "/drv/yycx/train/query?index=1", null, getHeaderMap(ticket));

    }

    public List<GovKSCX> getGovKSCX(GovSchoolTicket ticket) {
        List<GovKSCX> list = new ArrayList<GovKSCX>();
        list.add(new GovKSCX("C1", "C1"));
        list.add(new GovKSCX("C2", "C2"));
        list.add(new GovKSCX("A1", "A1"));
        list.add(new GovKSCX("A2", "A2"));
        list.add(new GovKSCX("A3", "A3"));
        list.add(new GovKSCX("B1", "B1"));
        list.add(new GovKSCX("B2", "B2"));
        list.add(new GovKSCX("C5", "C5"));
        return list;
    }

    @Override
    public List<GovKSKM> getGovKSKM(GovSchoolTicket ticket) {
        List<GovKSKM> list = new ArrayList<GovKSKM>();
        list.add(new GovKSKM("1", "科目一"));
        list.add(new GovKSKM("2", "科目二"));
        list.add(new GovKSKM("3", "科目三 道路驾驶技能考试"));
        list.add(new GovKSKM("4", "科目三 安全文明常识考试"));
        list.add(new GovKSKM("9", "科目二三"));
        return list;
    }

    @Override
    public List<GovKSDD> getGovKSDD(GovSchoolTicket ticket, String kskm) {
        String redisKey = "gov:" + ticket.getWebCode() + ":ksdd:" + kskm;
        //判断上次更新的时间点
        Object lastTimeObject = redisService.getValue(redisKey + ":lastTime");
        boolean needSync = true;
        if (lastTimeObject != null) {
            long lastTime = NumUtil.toLong(lastTimeObject.toString());
            //没超过一天，则不处理，直接使用
            if (System.currentTimeMillis() - lastTime < GlobalConstant.DAY_MILLIS) {
                needSync = false;
            }
        }

        if (needSync) {
            // 重新拉取cookie
            List<GovKSDD> list = null;
            try {
                list = loadksdd(ticket, kskm);
            } catch (BizException e) {
                return new ArrayList<GovKSDD>();
            }
            redisService.saveValue(redisKey, list, 0);
            return list;
        } else {
            return (List<GovKSDD>) redisService.getValue(redisKey);
        }
    }


    private List<GovKSDD> loadksdd(GovSchoolTicket ticket, String kskm) throws BizException {
        Map<String, String> param = new HashMap<String, String>();
        Map<String, String> header = getHeaderMap(ticket);
        param.put("kskm", kskm);

        List<GovKSDD> arrayList = new ArrayList<GovKSDD>();
        String jsonStr = HttpClientUtil.post("http://" + ticket.getWebCode() + "/drv/yycx/train/loadksdd", param, header);

        if (StringUtils.isNotBlank(jsonStr)) {
            JSONObject jsonObject = JsonUtils.toJSONObject(jsonStr);
            if (jsonSuccessCode.equals(jsonObject.getString("code"))) {
                JSONArray jsonArray = jsonObject.getJSONArray("data");
                int l = jsonArray.size();
                for (int i = 0; i < l; i++) {
                    JSONObject jObject = jsonArray.getJSONObject(i);
                    GovKSDD bean = new GovKSDD(kskm, jObject.getString("kcdddh"), jObject.getString("kcmc"));
                    arrayList.add(bean);
                }
            }
        }

        return arrayList;
    }

    @Override
    public int syncYK(GovSchoolTicket ticket, GovExSyncTask task) throws BizException {
        int re = 0;
        Date endTime = Calendar.getInstance().getTime();
        List<GovKSCX> kscxList = getGovKSCX(ticket);
        List<GovKSKM> kskmList = getGovKSKM(ticket);
        for (GovKSKM kskm : kskmList) {
            List<GovKSDD> govKSDDList = getGovKSDD(ticket, kskm.getCode());
            for (GovKSDD ksdd : govKSDDList) {
                for (GovKSCX kscx : kscxList) {
                    re += syncYK(endTime, ticket, task, kskm, ksdd, kscx);
                }
            }
        }
        return re;
    }

    private int syncYK(Date endTime, GovSchoolTicket ticket, GovExSyncTask task, GovKSKM kskm, GovKSDD ksdd, GovKSCX kscx) throws BizException {
        int re = 0;
        int pageIndex = 1;
        int pageSize = 10;

        Map<String, String> params = new HashMap<String, String>();
        params.put("type", "1");
        params.put("index", "1");
        params.put("ykrqstart", DateUtils.getDateString(task.getTimeLine()));
        params.put("ykrqend", DateUtils.getDateString(endTime));
        params.put("kskm", kskm.getCode());
        params.put("kscx", kscx.getCode());
        params.put("ksdd", ksdd.getCode());
        params.put("xm", "");//姓名
        params.put("sfzmhm", "");//身份证
        int csize = 0;

        List<AddStudentExamRo> roList = new ArrayList<AddStudentExamRo>(pageSize);
        do {
            roList.clear();
            csize = 0;
            params.put("page", pageIndex + "");
            params.put("size", pageSize + "");
            log.info("开始获取约考记录：" + kscx.getName() + " " + kskm.getName() + " " + ksdd.getName());
            String html = HttpClientUtil.post("http://" + ticket.getWebCode() + "/drv/yycx/train/executequery", params, getHeaderMap(ticket));


            Document doc = Jsoup.parse(html);
            Elements list = doc.select(".queryResultDiv tbody tr");
            if (list.size() == 1 && list.get(0).children().size() < 5) {
                // log.info("不解析");
                // log.info(list.get(0).outerHtml());
                break;
            }

            for (Element element : list) {
                csize++;
                Elements tdList = element.children();
                log.info(element.outerHtml());

                AddStudentExamRo bean = new AddStudentExamRo();
                bean.setDriverId(ticket.getSchoolId());
                bean.setName(tdList.get(0).text());
                bean.setExamSubject(NumUtil.toInt( kskm.getCode()));
                bean.setExamCarModel(kscx.getCode());
                bean.setExamReadyTime(DateUtils.toDate(tdList.get(3).text()));
                bean.setExamTime(DateUtils.toDate(tdList.get(4).text()));
                bean.setExamAddress(tdList.get(5).text());
                bean.setExamRound(tdList.get(6).text());
                roList.add(bean);
            }

            if (roList.size() > 0) {
                examService.addStudentExamYK(roList);
            }

            re += csize;
            pageIndex++;
        } while (csize == pageSize);//分页足条，说明非常可能有下页

        sleep();
        return re;
    }

    @Override
    public int syncCJ(GovSchoolTicket ticket, GovExSyncTask task) throws BizException {
        int re = 0;
        Date endTime = Calendar.getInstance().getTime();
        List<GovKSCX> kscxList = getGovKSCX(ticket);
        List<GovKSKM> kskmList = getGovKSKM(ticket);
        for (GovKSKM kskm : kskmList) {
            List<GovKSDD> govKSDDList = getGovKSDD(ticket, kskm.getCode());
            for (GovKSDD ksdd : govKSDDList) {
                for (GovKSCX kscx : kscxList) {
                    re += syncCJ(endTime, ticket, task, kskm, ksdd, kscx);
                }
            }
        }
        return re;
    }


    private int syncCJ(Date endTime, GovSchoolTicket ticket, GovExSyncTask task, GovKSKM kskm, GovKSDD ksdd, GovKSCX kscx) throws BizException {
        int re = 0;
        int pageIndex = 1;
        int pageSize = 10;

        Map<String, String> params = new HashMap<String, String>();
        params.put("type", "2");
        params.put("index", "2");
        params.put("ksrqstart", DateUtils.getDateString(task.getTimeLine()));
        params.put("ksrqend", DateUtils.getDateString(endTime));
        params.put("kskm", kskm.getCode());
        params.put("kscx", kscx.getCode());
        params.put("ksdd", ksdd.getCode());
        params.put("xm", "");//姓名
        params.put("sfzmhm", "");//省份中

        List<AddStudentFieldRo> roList = new ArrayList<AddStudentFieldRo>(pageSize);
        int csize = 0;
        do {
            csize = 0;
            roList.clear();
            params.put("page", pageIndex + "");
            params.put("size", pageSize + "");
            log.info("开始获取成绩记录：" + kscx.getName() + " " + kskm.getName() + " " + ksdd.getName());

            String html = HttpClientUtil.post("http://" + ticket.getWebCode() + "/drv/yycx/train/executequery", params, getHeaderMap(ticket));

            Document doc = Jsoup.parse(html);

            Elements list = doc.select(".queryResultDiv tbody tr");
            if (list.size() == 1 && list.get(0).children().size() < 5) {
                log.info("不解析");
                log.info(list.get(0).outerHtml());
                break;
            }

            for (Element element : list) {
                csize++;
                Elements tdList = element.children();
                log.info(element.outerHtml());

                AddStudentFieldRo bean = new AddStudentFieldRo();
                bean.setDriverId(ticket.getSchoolId());
                bean.setName(tdList.get(0).text());
                bean.setExamSubject(NumUtil.toInt( kskm.getCode()));
                bean.setExamCarModel(kscx.getCode());
                bean.setExamTime(DateUtils.toDate(tdList.get(3).text()));
                bean.setExamAddress(tdList.get(4).text());
                bean.setExamRound(tdList.get(5).text());
                bean.setExamField(tdList.get(6).text());
                int score = NumUtil.toInt(bean.getExamField());


                int minSocre = 90;
                if (kskm.getCode().equals("2")) {
                    if (kscx.getCode().equals("A1") || kscx.getCode().equals("A2")) {
                        minSocre = 90;
                    } else {
                        minSocre = 80;
                    }
                }

                if (score >= minSocre) {
                    bean.setFieldStatus(FieldStatus.ok);
                } else {
                    bean.setFieldStatus(FieldStatus.fail);
                }

                roList.add(bean);
            }
            if (roList.size() > 0) {
                examService.addStudentExamResult(roList);
            }
            re += csize;
            pageIndex++;
        } while (csize == pageSize);//分页足条，说明非常可能有下页

        sleep();
        return re;
    }


    @Override
    public int syncYLR(GovSchoolTicket ticket, GovExSyncTask task) throws BizException {
        //预约录入结果查询
        //一周内的，根据条件查询
        int re = 0;
        int pageIndex = 1;
        int pageSize = 10;

        Map<String, String> params = new HashMap<String, String>();
        params.put("xm", "");
        params.put("yhdh", "");
        params.put("sfzmhm", "");
        params.put("sfzmmc", "");
        params.put("zkcx", "");
        params.put("ywzt", "");

        Calendar start = Calendar.getInstance();
        start.add(Calendar.DATE, 7);
        Calendar end = Calendar.getInstance();
        params.put("gxrqstart", DateUtils.getDateString(start.getTime()));
        params.put("gxrqend", DateUtils.getDateString(end.getTime()));
        int csize = 0;
        do {
            csize = 0;
            params.put("page", pageIndex + "");
            params.put("size", pageSize + "");
            log.info("开始获取成绩记录：预录入结果");

            String jsonStr = HttpClientUtil.post("http://" + ticket.getWebCode() + "/drv/sl/list", params, getHeaderMap(ticket));

            JSONObject jsonObject = JsonUtils.toJSONObject(jsonStr);
            int code = jsonObject.getIntValue("code");
            if (code == 200) {
                JSONArray jsonList = jsonObject.getJSONArray("content");
                int size = jsonList.size();
                for (int i = 0; i < size; i++) {
                    csize++;
                    JSONObject jobject = jsonList.getJSONObject(i);
                    String xm = jsonObject.getString("xm");
                    String lyStr = jsonObject.getString("lyStr");
                    String ywlxStr = jsonObject.getString("ywlxStr");
                    String sfzmhm = jsonObject.getString("sfzmhm");//注意：可能没有
                    String zkcx = jsonObject.getString("zkcx");
                    String ywzt = jsonObject.getString("ywzt");//状态A：待受理，L:办结，F：退办
                    String fkxx = jsonObject.getString("fkxx");//反馈信息
                    String gxrq = jsonObject.getString("gxrq");//录入日期
                    String wwlsh = jsonObject.getString("wwlsh");//流水号

                    if (StringUtils.isNotBlank(sfzmhm)) {
                        if ("l".equalsIgnoreCase(ywzt)) {
                            exRegisterTaskService.saveConfirmSuccess(sfzmhm, RegisterTaskType.api, true);
                        } else if ("f".equalsIgnoreCase(ywzt)) {
                            CheckResultFailDTO dto=new CheckResultFailDTO();
                            dto.setIdNo(sfzmhm);
                            dto.setSerialNumber(wwlsh);
                            dto.setFeedbackResult(fkxx);
                            dto.setApplyTime(DateUtils.toDate(gxrq));
                            exRegisterTaskService.saveConfirmFailed(dto, RegisterTaskType.api, true);
                        }
                    } else {
                        log.warn("没找到身份证明号码,姓名：" + xm);
                    }
                }
            }
            re += csize;
            pageIndex++;
        } while (csize == pageSize);//分页足条，说明非常可能有下页

        //根据超出一周的，根据证件号码补充查询
        return re;
    }

    private void sleep() {
       /* try {
            //随机休眠,避免短时间内频繁处理数据，被停止掉
            Thread.sleep(new Random().nextInt(2000));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }*/
    }
}
